package com.ctools;


import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.operation.buffer.BufferParameters;
import org.locationtech.jts.operation.polygonize.Polygonizer;
import java.util.ArrayList;
import java.util.Arrays;


/**
 * Geometry空间矢量数据操作工具类
 * Gis开发相关操作
 */
public class GeoTools {




    /**
     * 计算两个MULTIPOLYGON坐标之间相交的面
     * @param multipolygon1WKT
     * @param multipolygon2WKT
     * @param SRID 空间参考系
     * @return Intersection: POLYGON ((3 5, 5 5, 5 3, 4 3, 4 1, 1 1, 1 4, 3 4, 3 5))
     */
    public static String checker(String multipolygon1WKT, String multipolygon2WKT,int SRID) {
        // 创建GeometryFactory实例
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建WKTReader实例
        WKTReader wktReader = new WKTReader(geometryFactory);
        try {
            // 解析MULTIPOLYGON字符串创建Geometry对象
            Geometry multipolygon1 = wktReader.read(multipolygon1WKT);
            Geometry multipolygon2 = wktReader.read(multipolygon2WKT);
            // 使用Buffer函数对多边形进行缓冲区操作
            double bufferDistance = 0.0;  // 缓冲区距离
            Geometry bufferedMultipolygon1 = multipolygon1.buffer(bufferDistance, BufferParameters.CAP_ROUND);
            Geometry bufferedMultipolygon2 = multipolygon2.buffer(bufferDistance, BufferParameters.CAP_ROUND);
            // 判断两个Geometry对象是否相交
            if (bufferedMultipolygon1.intersects(bufferedMultipolygon2)) {
                // 获取两个MULTIPOLYGON的交集
                Geometry intersection = bufferedMultipolygon1.intersection(bufferedMultipolygon2);
                // 判断几何对象的类型
                if (intersection instanceof MultiPolygon || intersection instanceof Polygon) {
                    return intersection.toText();
                } else {
                    GeometryCollection geometryCollection = geometryFactory.createGeometryCollection(new Geometry[]{intersection});
                    // 转换为 MultiPolygon 或 Polygon
                    Geometry convertedGeometry = geometryCollection.convexHull();
                    return convertedGeometry.toText();
                }
            } else {
                System.out.println("No intersection found.");
                return "FAIL";
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return "FAIL";
    }



    /**
     * 计算平面面积
     * @param wkt
     * @param SRID
     * @return
     */
    public static double AreaCalculation(String wkt, Integer SRID) {
        double area = 0.0;
        try {
            // 创建GeometryFactory实例
            GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
            // 创建WKTReader对象并解析WKT字符串为Geometry对象
            WKTReader wktReader = new WKTReader(geometryFactory);
            Geometry geometry = wktReader.read(wkt);
            // 计算几何对象的面积
            area = geometry.getArea();
            System.out.println("Area: " + area);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String valueOf = String.valueOf(area);
        valueOf = valueOf.length() > 6 ? valueOf.substring(0, 6) : valueOf;
        return Double.valueOf(valueOf);
    }


    /**
     * 返回擦除后相交平面
     * @param SRID 空间参考系
     * @param needWkt
     * @param useWkt
     */
    public static String erase(String needWkt, String useWkt,int SRID) {
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建WKTReader对象并解析WKT字符串为Geometry对象
        WKTReader wktReader = new WKTReader(geometryFactory);
        try {
            Geometry multipolygon1 = wktReader.read(needWkt);
            if (!multipolygon1.isValid()) {
                multipolygon1.buffer(0);
            }
            Geometry multipolygon2 = wktReader.read(useWkt);
            if (!multipolygon2.isValid()) {
                multipolygon2.buffer(0);
            }
            Geometry difference = multipolygon1.difference(multipolygon2);
            String toText = difference.toText();
            return toText;
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 合并两个平面为一个面，返回合并值
     * @param SRID 空间参考系
     * @param WKT1
     * @param WKT2
     * @return
     */
    public static String unionMultiPolygon(String WKT1, String WKT2,int SRID) {
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建WKTReader对象并解析WKT字符串为Geometry对象
        WKTReader wktReader = new WKTReader(geometryFactory);
        try {
            Geometry multipolygon1 = wktReader.read(WKT1);
            if (!multipolygon1.isValid()) {
                multipolygon1.buffer(0);
            }
            Geometry multipolygon2 = wktReader.read(WKT2);
            if (!multipolygon2.isValid()) {
                multipolygon2.buffer(0);
            }
            // 创建 GeometryCollection 对象并添加多个 Polygon 和 MultiPolygon
            GeometryCollection geometryCollection = new GeometryCollection(new Geometry[]{multipolygon1, multipolygon2}, geometryFactory);
            // 合并为一个 MultiPolygon
            Geometry union = multipolygon1.union(multipolygon2);
            // 对 GeometryCollection 进行缓冲区操作
            double bufferDistance = 0.0;  // 根据需要调整缓冲区距离
            Geometry bufferedGeometry = geometryCollection.buffer(bufferDistance);
            // 对缓冲后的几何对象进行拓扑校正
            Geometry result = fixTopology(union,SRID);
            // 检查合并结果
            if (result instanceof MultiPolygon) {
                System.out.println("成功合并MultiPolygon: " + result);
                return result.toText();
            } else {
                System.out.println("合并结果不是一个MultiPolygon.");
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }





    /**
     * 拓扑校正，消除重叠边界
     * @param geometry
     * @param SRID 空间参考系
     * @return
     */
    private static Geometry fixTopology(Geometry geometry,int SRID) {
        Polygonizer polygonizer = new Polygonizer();
        polygonizer.add(geometry);
        Geometry correctedGeometry = polygonizer.getGeometry();
        MultiPolygon multiPolygon = null;
        if (correctedGeometry instanceof GeometryCollection) {
            GeometryCollection geometryCollection = (GeometryCollection) geometry;
            int numGeometries = geometryCollection.getNumGeometries();
            Polygon[] polygons = new Polygon[numGeometries];
            for (int i = 0; i < numGeometries; i++) {
                Geometry geometryN = geometryCollection.getGeometryN(i);
                if (geometryN instanceof Polygon) {
                    polygons[i] = (Polygon) geometryN;
                }
            }
            ArrayList<Polygon> polygonsList = new ArrayList<>(Arrays.asList(polygons));
            for (int i = 0; i < polygonsList.size(); i++) {
                if (polygonsList.get(i) == null) {
                    polygonsList.remove(polygons[i]);
                }
            }
            Polygon[] polygonArray = new Polygon[polygonsList.size()];
            polygonArray = polygonsList.toArray(polygonArray);
            GeometryFactory factory = new GeometryFactory(new PrecisionModel(), SRID);
            multiPolygon = factory.createMultiPolygon(polygonArray);
        }
        return multiPolygon;
    }


    /**
     * 判断两个面是否相交
     * @param multipolygon1WKT
     * @param multipolygon2WKT
     * @param SRID 空间参考系
     * @return
     */
    public static boolean isIntersects(String multipolygon1WKT, String multipolygon2WKT,int SRID) {
        // 创建GeometryFactory实例
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建WKTReader实例
        WKTReader wktReader = new WKTReader(geometryFactory);
        try {
            // 解析MULTIPOLYGON字符串创建Geometry对象
            Geometry multipolygon1 = wktReader.read(multipolygon1WKT);
            Geometry multipolygon2 = wktReader.read(multipolygon2WKT);
            // 使用Buffer函数对多边形进行缓冲区操作
            double bufferDistance = 0.0;  // 缓冲区距离
            Geometry bufferedMultipolygon1 = multipolygon1.buffer(bufferDistance, BufferParameters.DEFAULT_QUADRANT_SEGMENTS);
            Geometry bufferedMultipolygon2 = multipolygon2.buffer(bufferDistance, BufferParameters.DEFAULT_QUADRANT_SEGMENTS);
            return bufferedMultipolygon1.intersects(bufferedMultipolygon2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 判断multipolygon是否是一条直线
     * @param WKT
     * @param SRID 空间参考系
     * @return
     */
    public static boolean isSimple(String WKT,int SRID) {
        // 创建GeometryFactory实例
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建WKTReader实例
        WKTReader wktReader = new WKTReader(geometryFactory);
        try {
            Geometry geometry = wktReader.read(WKT);
            // 检查合并结果
            if (geometry instanceof MultiPolygon) {
                MultiPolygon multipolygon = (MultiPolygon) geometry;
                // 判断是否为一条直线
                if (multipolygon.isSimple()) {
                    System.out.println("多边形是一条直线");
                    return true;
                } else {
                    System.out.println("多边形不是一条直线");
                    return false;
                }
            } else if (geometry instanceof Polygon) {
                Polygon Polygon = (Polygon) geometry;
                // 判断是否为一条直线
                if (Polygon.isSimple()) {
                    System.out.println("多边形是一条直线");
                    return true;
                } else {
                    System.out.println("多边形不是一条直线");
                    return false;
                }
            } else {
                return false;
            }
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 查找矢量中心点
     * @param WKT
     * @param SRID 空间参考系
     * @return
     */
    public static String getCentroid(String WKT,int SRID) {
        try {
            Geometry geometry = new WKTReader().read(WKT);
            // 获取中心点
            Geometry centroid = geometry.getCentroid();
            return centroid.toText();
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 判断点是否在平面内
     * @param point_x
     * @param point_y
     * @param WKT
     * @param SRID 空间参考系
     * @return
     * @throws ParseException
     */
    public static boolean isContains(double point_x, double point_y, String WKT,int SRID) throws ParseException {
        GeometryFactory geomFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建平面上的点
        Coordinate pointCoord = new Coordinate(point_x, point_y);
        // 创建多边形
        WKTReader reader = new WKTReader(geomFactory);
        Polygon polygon = (Polygon) reader.read(WKT);
        // 创建点对象
        Point point = geomFactory.createPoint(pointCoord);
        // 判断点是否在多边形内部
        boolean contains = polygon.contains(point);
        if (contains) {
            System.out.println("点在平面内");
        } else {
            System.out.println("点没有在平面内");
        }
        return contains;
    }

    /**
     * 判断两个面是否相交
     * @param multipolygon1WKT
     * @param multipolygon2WKT
     * @param SRID 空间参考系
     * @return
     */
    public static boolean isContains(String multipolygon1WKT, String multipolygon2WKT,int SRID) {
        // 创建GeometryFactory实例
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), SRID);
        // 创建WKTReader实例
        WKTReader wktReader = new WKTReader(geometryFactory);
        try {
            // 解析MULTIPOLYGON字符串创建Geometry对象
            Geometry multipolygon1 = wktReader.read(multipolygon1WKT);
            Geometry multipolygon2 = wktReader.read(multipolygon2WKT);
            // 使用Buffer函数对多边形进行缓冲区操作
            double bufferDistance = 0.0;  // 缓冲区距离
            Geometry bufferedMultipolygon1 = multipolygon1.buffer(bufferDistance, BufferParameters.DEFAULT_QUADRANT_SEGMENTS);
            Geometry bufferedMultipolygon2 = multipolygon2.buffer(bufferDistance, BufferParameters.DEFAULT_QUADRANT_SEGMENTS);
            return bufferedMultipolygon1.contains(bufferedMultipolygon2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 根据wkt创建空间矢量Geometry对象
     * @param wkt
     * @param srid
     * @return
     */
    public static Geometry createGeometry(String wkt, int srid) {
        if (wkt.isEmpty()) {
            return null;
        }
        try {
            WKTReader reader = new WKTReader();
            Geometry geometry = reader.read(wkt);
            geometry.setSRID(srid);
            return geometry;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
